/*
 * $Id$
 *
 * Copyright (C) Paris8-IUT de Montreuil, 2012-2013
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation; either version 2.1 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 * 
 * You should have received a copy of the GNU Lesser General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
 */
package fr.paris8.iut.info.iddl;

import fr.inrialpes.exmo.align.parser.AlignmentParser;
import fr.inrialpes.exmo.align.impl.BasicAlignment;
import fr.inrialpes.exmo.align.impl.ObjectAlignment;

import fr.paris8.iut.info.iddl.conf.GlobalEquivalentConcepts;
import fr.paris8.iut.info.iddl.conf.GlobalEquivalentRoles;
import fr.paris8.iut.info.iddl.conf.LocalEntityMap;
import fr.paris8.iut.info.iddl.conf.RoleConfTriple;
import fr.paris8.iut.info.iddl.conf.SystemData;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.URI;
import java.net.URL;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;
import java.util.Collection;
import java.util.LinkedList;
import java.util.ArrayList;
import java.util.Set;
import java.util.NoSuchElementException;
import java.util.Enumeration;
import javax.swing.JTextArea;

import org.semanticweb.owl.align.Alignment;
import org.semanticweb.owlapi.apibinding.OWLManager;
import org.semanticweb.owlapi.model.OWLClass;
import org.semanticweb.owlapi.model.OWLObjectPropertyExpression;
import org.semanticweb.owlapi.model.OWLOntology;
import org.semanticweb.owlapi.model.OWLOntologyID;
import org.semanticweb.owlapi.model.OWLOntologyChange;
import org.semanticweb.owlapi.model.AddAxiom;
import org.semanticweb.owlapi.model.OWLOntologyManager;
import org.semanticweb.owlapi.model.OWLClassAxiom;
import org.semanticweb.owlapi.model.OWLSubClassOfAxiom;
import org.semanticweb.owlapi.model.OWLClassAssertionAxiom;
import org.semanticweb.owlapi.model.OWLObjectPropertyAssertionAxiom;
import org.semanticweb.owlapi.model.OWLDataPropertyAssertionAxiom;

import org.semanticweb.owlapi.reasoner.NodeSet;
import org.semanticweb.owlapi.reasoner.Node;

import org.semanticweb.owlapi.model.IRI;
import org.semanticweb.owlapi.model.OWLAxiom;
import org.semanticweb.owlapi.model.OWLIndividual;
import org.semanticweb.owlapi.model.OWLNamedIndividual;
import org.semanticweb.owlapi.model.OWLLiteral;
import org.semanticweb.owlapi.model.OWLDatatype;
import org.semanticweb.owlapi.model.OWLDataRange;
import org.semanticweb.owlapi.model.OWLIndividualAxiom;
import org.semanticweb.owlapi.model.OWLProperty;
import org.semanticweb.owlapi.model.OWLObjectProperty;
import org.semanticweb.owlapi.model.OWLDataProperty;
import org.semanticweb.owlapi.model.OWLPropertyAxiom;
import org.semanticweb.owlapi.model.OWLObjectSomeValuesFrom;
import org.semanticweb.owlapi.model.OWLObjectAllValuesFrom;
import org.semanticweb.owlapi.model.OWLDataAllValuesFrom;
import org.semanticweb.owlapi.model.OWLOntologyCreationException;
import org.semanticweb.owlapi.util.OWLOntologyChangeVisitorAdapter;
import org.w3c.dom.Document;
import org.xml.sax.SAXException;

import uk.ac.manchester.cs.owl.owlapi.OWLDataFactoryImpl;
import uk.ac.manchester.cs.owl.owlapi.OWLOntologyImpl;


public class IDDLReasonerImpl {
	
	private Vector<URI>   alignUris = null;
	private SystemData    systemData = null;
	private LocalReasoner reasoner = null;
	private OWLDataFactoryImpl facto = null;
	private OWLOntologyChangeVisitorAdapter changeVisitor =null;
	private IDDLExplanation explanation = null;
	
	private HashMap<String, GlobalEquivalentConcepts> equivClsOfConcepts = null;
	private HashMap<String, GlobalEquivalentRoles>    equivClsOfRoles = null;
	private Set<String> representativeConcepts = null;
	private Set<String> representativeRoles = null;
	private HashMap<String, Set<String>> conceptProjections = null;
	private HashMap<String, Set<String>> roleProjections = null;
	
	private Set<String> quanta =  null;
	private Set<String> initConf   = null;
	private Set<Set<String>> confIter = null;
	private LocalReasoner localReasoner = null;
	
	private static int globalEntityId = 0 ;
	private static int globalOntoName = 0 ;
	private static int localEntityId = 0 ;
	private static File rootOnto = null;
	

	//there is no "/" at the end of "uriRoot"
	//public static String uriRoot =  "file:" + rootOnto.getAbsolutePath() + "/";
	public final static String uriRoot = "http://exmo.inrialpes.fr/iddl/";
	//rethink : a temporary way for allowing addAlignment(Alignment)
	Hashtable<String,Alignment>  alignTable = new Hashtable<String,Alignment>();
	
	public IDDLReasonerImpl( LocalReasoner reasoner) {
		   localReasoner = reasoner;
	}

	public void addAlignment(Alignment align){
	       alignTable.put( Integer.toString(getGlobalEntityId()) , align );
	}
	
	//"uris" are uris of "Alignment"
	public void loadIDDLSystem (  Vector<URI> uris ) {
		
		alignUris = uris;
		explanation = new IDDLExplanation();
		
		//construct "systemData" from the whole system
		setSystemData( );
		//setSystemDataFromSys();
	 	System.out.println("Set System Data Done. ");
		equivClsOfConcepts = new HashMap();
		equivClsOfRoles = new HashMap();
		representativeConcepts = new HashSet();
		representativeRoles = new HashSet();
		quanta   = new HashSet();
		initConf = new HashSet();
		facto    = new OWLDataFactoryImpl();	
		reasoner = new LocalReasoner();
		changeVisitor = new OWLOntologyChangeVisitorAdapter();
		conceptProjections = new HashMap();
		roleProjections = new HashMap();
		
		if( uris.size() == 0 ) return;
		
		//get global concepts
		Collection<String> col1 = (Collection<String>)systemData.getGlobalConceptMap().values();
		Set<String> cNames = new HashSet<String>(col1);
	 
		//get global roles
		Collection<String> col2 = (Collection<String>)systemData.getGlobalRoleMap().values();
		Set<String> rNames = new HashSet<String>(col2);
		
		//fill "equivClsOfConcept"
		buildEquivClsOfConcepts( systemData.getOWLAlignmentOntology(), cNames );
		//fill "equivClsOfRoles"
		buildEquivClsOfRoles( systemData.getOWLAlignmentOntology(), rNames );
		
		//build concept representatives i.e. fill "allRepresentativeConcepts"
		representativeConcepts = equivClsOfConcepts.keySet();
		
		System.out.println("Number of representative concepts= " +  representativeConcepts.size() + "("+ cNames.size() +")");
		
		//build role representatives i.e. fill "allEquivRoles"
		representativeRoles = equivClsOfRoles.keySet();
		
		System.out.println("Number of representative roles= " +  representativeRoles.size() + "("+ rNames.size() +")"); 
		
		for(String ck : representativeConcepts) {
			if(equivClsOfConcepts.get(ck).getEmptyness() == 2 ) {
				//System.out.println("ck="+ck);
				//System.out.println("representative="+ equivClsOfConcepts.get(ck).getRepresentative());
				quanta.add( ck );
			}
			
			if(equivClsOfConcepts.get(ck).getEmptyness() == 0 )
				initConf.add( ck );
		}
		
		System.out.println("Number of quantic concepts= " +  quanta.size()  );
		System.out.println("Number of non-empty concepts= " +  initConf.size()  ); 
		
		//System.out.println( "quanta="+ systemData.getLCsByGC(quanta.toString()) );
		//System.out.println( "initConf="+ systemData.getLCsByGC(initConf.toString()));
		//System.out.println( "quanta="+ quanta.size() );
		//System.out.println( "initConf="+ initConf.size() );
		
		buildLocalConceptProj( systemData.getLocalMap().getLocalUris() );
		//fill "roleProjections"
		buildLocalRoleProj( systemData.getLocalMap().getLocalUris() );
	}
	
	//"uris" are uris of "Mapping" 
	//public void loadMIDDLSystem (  Vector<URI> uris ) {
		
	//}
	
	public void unloadIDDLSystem ( ) {
		
		globalEntityId = 0;
		globalOntoName = 0;
		localEntityId = 0 ;
	}

	
	public void unloadMIDDLSystem (  Vector<URI> uris ) {
		globalEntityId = 0;
		globalOntoName = 0;
		localEntityId = 0 ;
	}	
	
	public static int getGlobalEntityId() {
		
		return globalEntityId++;
	}
	
	public static int getLocalEntityId() {
		
		return localEntityId++;
	}

	public static int getGlobalOntoName() {
		
		return globalOntoName++;
	}
	
	public void setSystemDataFromSys ( ) {
		systemData = new SystemData( alignUris );
	}
	
	public String getExplanation() {
		return explanation.getExplanation();
	}
	
	public SystemData getSystemData ( ) {
		return systemData;
	}
	
	//fill "systemData" 
	public void setSystemData ( ) {
		int fileId=0;
		
		//Hashtable<String,Alignment>  alignTable = new Hashtable<String,Alignment>();
		String defaultHost = "aserv.inrialpes.fr";
		String defaultPort = "80";
		AlignServer onlineAlign = new AlignServer(defaultPort, defaultHost);
		try {
			AlignmentParser ap = new AlignmentParser( 0 );
		        ap.setEmbedded(true);
		    
			for(int i=0; i< alignUris.size(); i++) {
				
				//String rdfStr =  null;
				Alignment align = null;
				if(alignUris.get( i ).toString().startsWith("http://")) {
				    String rdfStr = onlineAlign.getRDFAlignment(alignUris.get( i ).toString());
				    align = (Alignment)ap.parseString(rdfStr);
				    //System.out.println("RDF="+rdfStr);
				    if(align == null) System.out.println("Online Align. Done: = null");
				    else  System.out.println("Online Align. Done : non null");
				    //System.out.println("Online Align. Done. ");
				}
				else {
				    System.out.println("Offline Align. Done. ");
				    align = (Alignment)ap.parse(alignUris.get( i ).toString());
				}
				
				alignTable.put( alignUris.get(i).toString(), align );
			}
		}
		catch ( Exception ex ) { ex.printStackTrace(); };
		
		systemData = new SystemData( alignTable );
	}
	
	public boolean checkInitSystem() {
		localReasoner.loadOntology( systemData.getOWLAlignmentOntology() );
		localReasoner.reasoner.getKB().realize();
		//if Alignment Ontology is inconsistent then the system is so
		if( !localReasoner.reasoner.isConsistent() ) {
			//System.out.println("The alignment ontology of the system is inconsistent!");
			explanation.setExplanation("<font color=\"red\">The alignment ontology of the system is inconsistent!</font>");
			return false;
		}
		localReasoner.dispose();
		//localReasoner.reasoner.unloadOntology( systemData.getOWLAlignmentOntology() );
		
		//for(String uri : systemData.getLocalUris()) {
		for(String uri : systemData.getAlignLocations()) {
			//if one Local Ontology is inconsistent then the system is so
			if( !localReasoner.isConsistent(uri, new HashSet<OWLAxiom>()) ) {
				//System.out.println("Local ontology : "+uri+ " is inconsistent!");
				explanation.setExplanation("<font color=\"red\">Local ontology : "+uri+ " is inconsistent!</font>");
				return false;
			}
		}
		
		return true;
	}
	
        //Condition : there is no disjointness axiom in alignments, the alg. does not distinguish "dataRole" from "objectRole"
	//It considers all roles as objectRoles
	//Optimized algorithm
	public boolean isConsistent1() { 	
		//if there is no alignment, the system is consistent !!! 
		if(alignUris.size()==0) return true;
		if (! checkInitSystem() ) return false;
		//for each global concept configuration
		PowerSet powerSetC = new PowerSet(quanta.toArray());
		
		boolean someConsistentExAlign = false;
		
		//conf is initialized as empty
		int check = 0;
		boolean startedC = true;
		Set<String> conf = new HashSet<String>();
		while( powerSetC.hasNext()) {
			
			
			Set<String> compConf = null;
			if( startedC ) { 
		    	startedC = false;
		    	conf =  new HashSet<String>();
		    } else  {
		    	conf = (Set<String>)powerSetC.next();
		    	//compConfR = (Set<String>)powerSetR.next();
		    }
	 	
			//adding  the determined non-empty concepts 
			for(String st : initConf) conf.add(st);
		
			//System.out.println("Size of the considering concept configuration ("+ check++ +") ="+ conf.size() );
			
			
			System.out.println("Considering concept configuration ="+ conf );
			//System.out.println("Corresponding local concepts ="+ systemData.getLCsByGC(conf) );
		    
			//creating extended alignment ontology
			String ontoName = IDDLReasoner.uriRoot + getGlobalOntoName()+ ".owl";
			
			//for(String re : representativeConcepts) { 
			//	System.out.println("Rep. concepts ="+ re );
			//	System.out.println("Local Rep. concepts ="+ systemData.getLCsByGC(re) );
			//}
			
			Set<String> tmpConf = new HashSet<String>();
			for(String c : conf) tmpConf.add(c);
			
			Set<OWLAxiom> axsFromConceptConf = createGlobalAxiomsFromConceptConf( ontoName, tmpConf, representativeConcepts);
			
			//Set<Set<String>> allRoleConfs = subsets( representativeRoles );
			PowerSet powerSetR = new PowerSet(representativeRoles.toArray());
			
			//if role conf is empty
			if( !powerSetR.hasNext() ) {
				OWLOntology onto = createExAlignOntology(ontoName, axsFromConceptConf, new HashSet());
				 
				localReasoner.loadOntology( onto );
				//localReasoner.reasoner.getKB().realize();
		
				//if extented alignment ontology is not consistent, another "conf" and "roleConf"  will be considered
	
				if( localReasoner.reasoner.isConsistent() ) {
				    localReasoner.dispose();//.reasoner.unloadOntology( onto );
					someConsistentExAlign = true;
					Set<String> localUri = systemData.getLocalMap().getLocalUris();
			   
					boolean resByUri = true;
					for(String uri : localUri) {
						//System.out.println("Considering Ontology URI = "+ uri);
						Set<String> localConfC = buildLocalConceptProj(uri, conf ); 
						//Set<String> localConfR = buildLocalRoleProj(uri, roleConf );
				   
						//System.out.println("localConfR="+localConfR.toString());
				   
						String exOntoName = IDDLReasoner.uriRoot + getGlobalOntoName()+ ".owl";
						Set<OWLAxiom> localAxioms =  createLocalAxiomsFromConf(uri, localConfC, new HashSet());
						//OWLOntology exOnto = createExAlignOntology(exOntoName, localAxioms, new HashSet());
						
						//localReasoner.reasoner.loadOntology( exOnto );
						
						//if there is an extended local onto that is not consistent, we go to pick another "roleConf"
						if( ! localReasoner.isConsistent( uri, localAxioms) ) {
							//localReasoner.reasoner.unloadOntology( exOnto );
					   
							//System.out.println("Inconsistent Ontology URI = "+ uri);
							
							//Commented for memory
							//explanation.setExplanation("<font color=\"red\">Inconsistent ontology URI = "+ uri +"</font>");
							Set<String> localC = new HashSet();
							for(String st: conf) localC.add(systemData.getLCsByGC(st));
							//Commented for memory
							//explanation.setExplanation("Caused by the concept configuration :<br>" + explanation.explanationSetRenderer(localC));
							resByUri = false;
							break;
						}
					}
			   
					if ( resByUri ) return true;
				} else{
					
				    localReasoner.dispose();//reasoner.unloadOntology( onto );
				}
				
			} else {
				
			 
			  //If role conf. is not empty
			  //boolean rExit = false;
			  boolean started = true;
			  Set<String> roleConf = new HashSet<String>();
			  while( powerSetR.hasNext() ) {
				    
					//for each global role configuration
				    
				    Set<String> compConfR = null;
				    if( started ) { 
				    	started = false;
				    	roleConf =  new HashSet<String>();
				    } else  {
				    	roleConf = (Set<String>)powerSetR.next();
				    	//compConfR = (Set<String>)powerSetR.next();
				    }
				    
				    //Set<String> tmpSetR = new HashSet();
					//for(String q : representativeRoles) tmpSetR.add(q);
						
					//tmpSetR.removeAll(compConfR) ;
					 
					//for(String q : tmpSetR) roleConf.add(q);
				    
					//roleConf = compConfR;
				    		
				    //System.out.println("Size of considering role configuration ("+ check++ +")="+ roleConf.size() );
					System.out.println("Considering role configuration ="+ roleConf );
					//System.out.println("Corresponding local roles ="+ systemData.getLRsByGR(roleConf) );
				
					Set<String> tmpR = new HashSet<String>();
					for(String c : roleConf) tmpR.add(c);
					
					Set<OWLAxiom> axsFromRoleConf = createGlobalAxiomsFromRoleConf( ontoName, tmpR, representativeRoles );
				 
					OWLOntology onto = createExAlignOntology(ontoName, axsFromConceptConf, axsFromRoleConf);
				 
					localReasoner.loadOntology( onto );
					//localReasoner.reasoner.getKB().realize();
				 
					//if extented alignment ontology is not consistent, another "conf" and "roleConf"  will be considered
					
					if( localReasoner.reasoner.isConsistent() ) {
					    localReasoner.dispose();//reasoner.unloadOntology( onto );
						someConsistentExAlign = true;
						
						Set<String> localUri = systemData.getLocalMap().getLocalUris();
				   
						boolean resByUri = true;
						for(String uri : localUri) {
							//System.out.println("Considering Ontology URI = "+ uri);
							Set<String> localConfC = buildLocalConceptProj(uri, conf ); 
							Set<String> localConfR = buildLocalRoleProj(uri, roleConf );
					   
							//System.out.println("localConfR="+localConfR.toString());
					   
							String exOntoName = IDDLReasoner.uriRoot + getGlobalOntoName()+ ".owl";
							Set<OWLAxiom> localAxioms =  createLocalAxiomsFromConf(uri, localConfC, localConfR);
							//OWLOntology exOnto = createExAlignOntology(exOntoName, localAxioms, new HashSet());
					   
							//localReasoner.reasoner.loadOntology( exOnto );
							//if there is an extended local onto that is not consistent, we go to pick another "roleConf"
							if( ! localReasoner.isConsistent(uri, localAxioms) ) {
								//localReasoner.reasoner.unloadOntology( exOnto );   
								//System.out.println("Inconsistent Ontology URI = "+ uri);
								//
								//commented for memory
								//explanation.setExplanation("<font color=\"red\">Inconsistent ontology URI = "+ uri +"</font>");
								Set<String> localC = new HashSet();
								for(String st: conf) localC.add(systemData.getLCsByGC(st));
								//commented for memory
								//explanation.setExplanation("Caused by the concept configuration :<br>" + explanation.explanationSetRenderer(localC));
								for(String st: roleConf) localC.add(systemData.getLCsByGC(st));
								//commented for memory
								//explanation.setExplanation("Caused by the role configuration :<br>" + explanation.explanationSetRenderer(localC));
								resByUri = false;
								break;
							} else {
								
							}
							
						}//for "uri"
				   
						if ( resByUri ) return true;
					} else {
						
					    localReasoner.dispose();//reasoner.unloadOntology( onto );
					}
			  }//while for "confR"
			}// else
			
		} //while for "confC"
		
		if( !someConsistentExAlign ) 
			explanation.setExplanation("<font color=\"red\">All extended alignment ontologies are inconsistent! </font>");
		
        return false;
	}

	//Condition : there is no disjointness axiom in alignments, the alg. does not distinguish "dataRole" from "objectRole"
	//It considers all roles as objectRoles
	//Optimized algorithm
	public boolean isConsistent() throws OWLOntologyCreationException{
		//if there is no alignment, the system is consistent !!! 
		int size = 1;
		if(alignUris.size()==0) return true;
		if (! checkInitSystem() ) return false;

            
		//for each global concept configuration
				
		boolean someConsistentExAlign = false;
                HashMap historiqueIncons = new HashMap();

		
		//conf is initialized as empty
		int check = 0;
		boolean startedC = true;
		Set<String> conf = new HashSet<String>();
                PowerSetBySize powerSetC = new PowerSetBySize(quanta.toArray(),size);
		while(size<=quanta.size()){

			while( powerSetC.hasNext()) {			
			
				Set<String> compConf = null;
				if( startedC ) { 
			    	startedC = false;
			    	conf =  new HashSet<String>();
			    } else  {
			    	conf = (Set<String>)powerSetC.next();
			    	//compConfR = (Set<String>)powerSetR.next();
			    }
		 	
				//adding  the determined non-empty concepts 
				for(String st : initConf) conf.add(st);
		
				//System.out.println("Size of the considering concept configuration ("+ check++ +") ="+ conf.size() );
			
			
				System.out.println("Considering concept configuration ="+ conf );
				//System.out.println("Corresponding local concepts ="+ systemData.getLCsByGC(conf) );
			    
				//creating extended alignment ontology
				String ontoName = uriRoot + getGlobalOntoName()+ ".owl";
			
				//for(String re : representativeConcepts) { 
				//	System.out.println("Rep. concepts ="+ re );
				//	System.out.println("Local Rep. concepts ="+ systemData.getLCsByGC(re) );
				//}
			
				Set<String> tmpConf = new HashSet<String>();
				for(String c : conf) tmpConf.add(c);
			
				Set<OWLAxiom> axsFromConceptConf = createGlobalAxiomsFromConceptConfBySize( ontoName, tmpConf);
			
				//Set<Set<String>> allRoleConfs = subsets( representativeRoles );
				PowerSetBySize powerSetR = new PowerSetBySize(representativeRoles.toArray(),size);
			
				//if role conf is empty
				if( !powerSetR.hasNext() ) {
					
					OWLOntology onto = createExAlignOntology(ontoName, axsFromConceptConf, new HashSet());
				 
					localReasoner.loadOntology( onto );
					
					//localReasoner.reasoner.getKB().realize();
		
					//if extented alignment ontology is not consistent, another "conf" and "roleConf"  will be considered
                                         
                                       
					if(localReasoner.reasoner.isConsistent() ) {
					    localReasoner.reasoner.dispose();//.reasoner.unloadOntology( onto );
						someConsistentExAlign = true;
                                                
						Set<String> localUri = systemData.getLocalMap().getLocalUris();
				   
						boolean resByUri = true;
                                                Connector local1;
						for(String uri : localUri) {                                                    
                                                    if(!FindSetInSet(tmpConf, historiqueIncons,uri))
                                                    {
                                                        
							//System.out.println("Considering Ontology URI = "+ uri);
							Set<String> localConfC = buildLocalConceptProj(uri, conf ); 
							//Set<String> localConfR = buildLocalRoleProj(uri, roleConf );
					   
							//System.out.println("localConfR="+localConfR.toString());
					   
							String exOntoName = uriRoot + getGlobalOntoName()+ ".owl";
							Set<OWLAxiom> localAxioms =  createLocalAxiomsFromConf(uri, localConfC, new HashSet());
							//OWLOntology exOnto = createExAlignOntology(exOntoName, localAxioms, new HashSet());
						
							//localReasoner.reasoner.loadOntology( exOnto );
                                                       
							//if there is an extended local onto that is not consistent, we go to pick another "roleConf"
                                                        local1 = new Connector("http://127.0.0.1", 8081);
							if( ! local1.isConsistent(uri, localAxioms)){
							//if( ! localReasoner.isConsistent( uri, localAxioms, null) ) {
                                                                
                                                                historiqueIncons.put(uri,tmpConf);
								//localReasoner.reasoner.unloadOntology( exOnto );
						   
								//System.out.println("Inconsistent Ontology URI = "+ uri);
							
								//Commented for memory
								//explanation.setExplanation("<font color=\"red\">Inconsistent ontology URI = "+ uri +"</font>");
								Set<String> localC = new HashSet();
								for(String st: conf) localC.add(systemData.getLCsByGC(st));
								//Commented for memory
								//explanation.setExplanation("Caused by the concept configuration :<br>" + explanation.explanationSetRenderer(localC));
								resByUri = false;
								break;
							}
                                                    }
						}
				   
						if ( resByUri ){
							 System.out.println("Kich thuoc"+size);
							 return true;
						}
					} else{
					
					    localReasoner.reasoner.dispose();//reasoner.unloadOntology( onto );
					}
				
				} else {
				
				 
				  //If role conf. is not empty
				  //boolean rExit = false;;
				  boolean started = true;
				  Set<String> roleConf = new HashSet<String>();
				  while( powerSetR.hasNext() ) {
					    
						//for each global role configuration
					    
					    Set<String> compConfR = null;
					    if( started ) { 
					    	started = false;
					    	roleConf =  new HashSet<String>();
					    } else  {
					    	roleConf = (Set<String>)powerSetR.next();
					    	//compConfR = (Set<String>)powerSetR.next();
					    }
					    
					    //Set<String> tmpSetR = new HashSet();
						//for(String q : representativeRoles) tmpSetR.add(q);
						
						//tmpSetR.removeAll(compConfR) ;
						 
						//for(String q : tmpSetR) roleConf.add(q);
					    
						//roleConf = compConfR;
					    		
					    //System.out.println("Size of considering role configuration ("+ check++ +")="+ roleConf.size() );
						System.out.println("Considering role configuration ="+ roleConf );
						//System.out.println("Corresponding local roles ="+ systemData.getLRsByGR(roleConf) );
				
						Set<String> tmpR = new HashSet<String>();
						for(String c : roleConf) tmpR.add(c);
					
						Set<OWLAxiom> axsFromRoleConf = createGlobalAxiomsFromRoleConfBySize( ontoName, tmpR);
					 
						OWLOntology onto = createExAlignOntology(ontoName, axsFromConceptConf, axsFromRoleConf);
					 
						localReasoner.loadOntology(onto);
						//localReasoner.reasoner.getKB().realize();
					 
						//if extented alignment ontology is not consistent, another "conf" and "roleConf"  will be considered
                                                 
                                               
                                                if(localReasoner.reasoner.isConsistent() ) {
						    localReasoner.reasoner.dispose();//reasoner.unloadOntology( onto );
							someConsistentExAlign = true;
						
							Set<String> localUri = systemData.getLocalMap().getLocalUris();
					   
							boolean resByUri = true;
							for(String uri : localUri) {
                                                             if(!FindSetInSet(tmpConf, historiqueIncons,uri))
                                                            {
								//System.out.println("Considering Ontology URI = "+ uri);
								Set<String> localConfC = buildLocalConceptProj(uri, conf ); 
								Set<String> localConfR = buildLocalRoleProj(uri, roleConf );
						   
								//System.out.println("localConfR="+localConfR.toString());
						   
								String exOntoName = uriRoot + getGlobalOntoName()+ ".owl";
								Set<OWLAxiom> localAxioms =  createLocalAxiomsFromConf(uri, localConfC, localConfR);
								//OWLOntology exOnto = createExAlignOntology(exOntoName, localAxioms, new HashSet());
						   
								//localReasoner.reasoner.loadOntology( exOnto );
								//if there is an extended local onto that is not consistent, we go to pick another "roleConf"
                                                                Connector local2 = new Connector("http://127.0.0.1", 8081);
                                                                if( ! local2.isConsistent(uri, localAxioms)){
								//if( ! local.isConsistent(uri, localAxioms)){//localReasoner.isConsistent(uri, localAxioms, null) ) {
                                                                     historiqueIncons.put(uri,tmpConf);
									//localReasoner.reasoner.unloadOntology( exOnto );   
									//System.out.println("Inconsistent Ontology URI = "+ uri);
									//
									//commented for memory
									//explanation.setExplanation("<font color=\"red\">Inconsistent ontology URI = "+ uri +"</font>");
									Set<String> localC = new HashSet();
									for(String st: conf) localC.add(systemData.getLCsByGC(st));
									//commented for memory
									//explanation.setExplanation("Caused by the concept configuration :<br>" + explanation.explanationSetRenderer(localC));
									for(String st: roleConf) localC.add(systemData.getLCsByGC(st));
									//commented for memory
									//explanation.setExplanation("Caused by the role configuration :<br>" + explanation.explanationSetRenderer(localC));
									resByUri = false;
									break;
								} else {
								
								}
                                                             }
							
							}//for "uri"
					   
							if ( resByUri ){
							 System.out.println("Kich thuoc"+size);
							 return true;
							}
						} else {
						
						    localReasoner.reasoner.dispose();//reasoner.unloadOntology( onto );
						}
				  }//while for "confR"
				}// else
			
			} //while for "confC"
			size++;
		} //while for size
		
		if( !someConsistentExAlign ) 
			explanation.setExplanation("<font color=\"red\">All extended alignment ontologies are inconsistent! </font>");	
        return false;
	}

        public boolean isConsistentWithDisjonction() {
		//if there is no alignment, the system is consistent !!!
		if(alignUris.size()==0) return true;
		if (! checkInitSystem() ) return false;
		//for each global concept configuration
		PowerSet powerSetC = new PowerSet(quanta.toArray());

		boolean someConsistentExAlign = false;

		//conf is initialized as empty
		int check = 0;
		boolean startedC = true;
		Set<String> conf = new HashSet<String>();
		while( powerSetC.hasNext()) {


			Set<String> compConf = null;
			if( startedC ) {
		    	startedC = false;
		    	conf =  new HashSet<String>();
		    } else  {
		    	conf = (Set<String>)powerSetC.next();
		    	//compConfR = (Set<String>)powerSetR.next();
		    }

			//adding  the determined non-empty concepts
			for(String st : initConf) conf.add(st);

			//System.out.println("Size of the considering concept configuration ("+ check++ +") ="+ conf.size() );


			System.out.println("Considering concept configuration ="+ conf );
			//System.out.println("Corresponding local concepts ="+ systemData.getLCsByGC(conf) );

			//creating extended alignment ontology
			String ontoName = IDDLReasoner.uriRoot + getGlobalOntoName()+ ".owl";

			//for(String re : representativeConcepts) {
			//	System.out.println("Rep. concepts ="+ re );
			//	System.out.println("Local Rep. concepts ="+ systemData.getLCsByGC(re) );
			//}

			Set<String> tmpConf = new HashSet<String>();
			for(String c : conf) tmpConf.add(c);

			Set<OWLAxiom> axsFromConceptConf = createGlobalAxiomsFromConceptConf( ontoName, tmpConf, representativeConcepts);

			//Set<Set<String>> allRoleConfs = subsets( representativeRoles );
			PowerSet powerSetR = new PowerSet(representativeRoles.toArray());

			//if role conf is empty
			
			OWLOntology onto = createExAlignOntology(ontoName, axsFromConceptConf, new HashSet());

			localReasoner.loadOntology( onto );
				//localReasoner.reasoner.getKB().realize();

				//if extented alignment ontology is not consistent, another "conf" and "roleConf"  will be considered

			if( localReasoner.reasoner.isConsistent() ) {
			    localReasoner.dispose();//.reasoner.unloadOntology( onto );
                            someConsistentExAlign = true;
                            Set<String> localUri = systemData.getLocalMap().getLocalUris();

			    boolean resByUri = true;
			    for(String uri : localUri) {
				//System.out.println("Considering Ontology URI = "+ uri);
				Set<String> localConfC = buildLocalConceptProj(uri, conf );
				//Set<String> localConfR = buildLocalRoleProj(uri, roleConf );

				//System.out.println("localConfR="+localConfR.toString());

				String exOntoName = IDDLReasoner.uriRoot + getGlobalOntoName()+ ".owl";
				Set<OWLAxiom> localAxioms =  createLocalAxiomsForOntoEx(uri, localConfC);
				//if there is an extended local onto that is not consistent, we go to pick another "roleConf"
				if( ! localReasoner.isConsistent( uri, localAxioms) ) {
				//localReasoner.reasoner.unloadOntology( exOnto );

				//System.out.println("Inconsistent Ontology URI = "+ uri);

				//Commented for memory
				//explanation.setExplanation("<font color=\"red\">Inconsistent ontology URI = "+ uri +"</font>");
                                    Set<String> localC = new HashSet();
                                    for(String st: conf) localC.add(systemData.getLCsByGC(st));
							//Commented for memory
							//explanation.setExplanation("Caused by the concept configuration :<br>" + explanation.explanationSetRenderer(localC));
                                    resByUri = false;
                                    break;
				}
                            }

			    if ( resByUri ) return true;
			    } else{

			       localReasoner.dispose();//reasoner.unloadOntology( onto );
			    }		        
            }
         return false;
      }

        //Condition : there is no disjointness axiom in alignments, the alg. does not distinguish "dataRole" from "objectRole"
	//It considers all roles as objectRoles
	//Optimized algorithm
	public boolean isConsistentDistributed() throws OWLOntologyCreationException{
		//if there is no alignment, the system is consistent !!!
		int size = 1;
		if(alignUris.size()==0) return true;
		if (! checkInitSystem() ) return false;


		//for each global concept configuration

		boolean someConsistentExAlign = false;
                HashMap historiqueIncons = new HashMap();


		//conf is initialized as empty
		int check = 0;
		boolean startedC = true;
		Set<String> conf = new HashSet<String>();
                PowerSetBySize powerSetC = new PowerSetBySize(quanta.toArray(),size);
                ArrayList<Results> results = new ArrayList<Results>();
                ArrayList<Connector> locals = new ArrayList<Connector>();
		while(size<=quanta.size()){

			while( powerSetC.hasNext()) {

				Set<String> compConf = null;
				if( startedC ) {
			    	startedC = false;
			    	conf =  new HashSet<String>();
			    } else  {
			    	conf = (Set<String>)powerSetC.next();
			    	//compConfR = (Set<String>)powerSetR.next();
			    }

				//adding  the determined non-empty concepts
				for(String st : initConf) conf.add(st);

				//System.out.println("Size of the considering concept configuration ("+ check++ +") ="+ conf.size() );


				System.out.println("Considering concept configuration ="+ conf );
				//System.out.println("Corresponding local concepts ="+ systemData.getLCsByGC(conf) );

				//creating extended alignment ontology
				String ontoName = uriRoot + getGlobalOntoName()+ ".owl";

				//for(String re : representativeConcepts) {
				//	System.out.println("Rep. concepts ="+ re );
				//	System.out.println("Local Rep. concepts ="+ systemData.getLCsByGC(re) );
				//}

				Set<String> tmpConf = new HashSet<String>();
				for(String c : conf) tmpConf.add(c);

				Set<OWLAxiom> axsFromConceptConf = createGlobalAxiomsFromConceptConfBySize( ontoName, tmpConf);

				//Set<Set<String>> allRoleConfs = subsets( representativeRoles );
				PowerSetBySize powerSetR = new PowerSetBySize(representativeRoles.toArray(),size);

				//if role conf is empty
				if( !powerSetR.hasNext() ) {

					OWLOntology onto = createExAlignOntology(ontoName, axsFromConceptConf, new HashSet());

					localReasoner.loadOntology( onto );

					//localReasoner.reasoner.getKB().realize();

					//if extented alignment ontology is not consistent, another "conf" and "roleConf"  will be considered


					if(localReasoner.reasoner.isConsistent() ) {
					    localReasoner.reasoner.dispose();//.reasoner.unloadOntology( onto );
						someConsistentExAlign = true;

						Set<String> localUri = systemData.getLocalMap().getLocalUris();

						boolean resByUri = true;
                                                Connector local1;
                                                int k=0;
						for(String uri : localUri) {
                                                    if(!FindSetInSet(tmpConf, historiqueIncons,uri))
                                                    {

							//System.out.println("Considering Ontology URI = "+ uri);
							Set<String> localConfC = buildLocalConceptProj(uri, conf );
							//Set<String> localConfR = buildLocalRoleProj(uri, roleConf );

							//System.out.println("localConfR="+localConfR.toString());

							String exOntoName = uriRoot + getGlobalOntoName()+ ".owl";
							Set<OWLAxiom> localAxioms =  createLocalAxiomsFromConf(uri, localConfC, new HashSet());
							//OWLOntology exOnto = createExAlignOntology(exOntoName, localAxioms, new HashSet());

							//localReasoner.reasoner.loadOntology( exOnto );

							//if there is an extended local onto that is not consistent, we go to pick another "roleConf"
                                                        local1 = new Connector("http://127.0.0.1", 8081);
							results.add(new Results(local1.isConsistent(uri, localAxioms)));
							
							
                                                    }
						}
                                                int j=0,nbValid=0;
                                                while(nbValid<localUri.size())
                                                {
                                                    if(results.get(j).isValid()&&!results.get(j).getResult())
                                                    {
                                                        historiqueIncons.put(localUri.toArray()[j],tmpConf);
                                                        resByUri= false;
                                                        break;
                                                    }
                                                    else{
                                                        if(results.get(j).isValid()&&results.get(j).getResult()){
                                                            nbValid++;
                                                            j++;
                                                        }
                                                        else{
                                                            if(!results.get(j).isValid()){
                                                                j++;
                                                            }
                                                        }

                                                    }
                                                    if(j>=localUri.size()){
                                                        j=0;
                                                    }

                                                }
						if ( resByUri ){							 
							 return true;
						}
					} else{

					    localReasoner.reasoner.dispose();//reasoner.unloadOntology( onto );
					}

				} else {


				  //If role conf. is not empty
				  //boolean rExit = false;;
				  boolean started = true;
				  Set<String> roleConf = new HashSet<String>();
				  while( powerSetR.hasNext() ) {

						//for each global role configuration

					    Set<String> compConfR = null;
					    if( started ) {
					    	started = false;
					    	roleConf =  new HashSet<String>();
					    } else  {
					    	roleConf = (Set<String>)powerSetR.next();
					    	//compConfR = (Set<String>)powerSetR.next();
					    }

					    //Set<String> tmpSetR = new HashSet();
						//for(String q : representativeRoles) tmpSetR.add(q);

						//tmpSetR.removeAll(compConfR) ;

						//for(String q : tmpSetR) roleConf.add(q);

						//roleConf = compConfR;

					    //System.out.println("Size of considering role configuration ("+ check++ +")="+ roleConf.size() );
						System.out.println("Considering role configuration ="+ roleConf );
						//System.out.println("Corresponding local roles ="+ systemData.getLRsByGR(roleConf) );

						Set<String> tmpR = new HashSet<String>();
						for(String c : roleConf) tmpR.add(c);

						Set<OWLAxiom> axsFromRoleConf = createGlobalAxiomsFromRoleConfBySize( ontoName, tmpR);

						OWLOntology onto = createExAlignOntology(ontoName, axsFromConceptConf, axsFromRoleConf);

						localReasoner.loadOntology(onto);
						//localReasoner.reasoner.getKB().realize();

						//if extented alignment ontology is not consistent, another "conf" and "roleConf"  will be considered


                                                if(localReasoner.reasoner.isConsistent() ) {
						    localReasoner.reasoner.dispose();//reasoner.unloadOntology( onto );
							someConsistentExAlign = true;

							Set<String> localUri = systemData.getLocalMap().getLocalUris();

							boolean resByUri = true;
							for(String uri : localUri) {
                                                            if(!FindSetInSet(tmpConf, historiqueIncons,uri))
                                                            {
								//System.out.println("Considering Ontology URI = "+ uri);
								Set<String> localConfC = buildLocalConceptProj(uri, conf );
								Set<String> localConfR = buildLocalRoleProj(uri, roleConf );

								//System.out.println("localConfR="+localConfR.toString());

								String exOntoName = uriRoot + getGlobalOntoName()+ ".owl";
								Set<OWLAxiom> localAxioms =  createLocalAxiomsFromConf(uri, localConfC, localConfR);
								//OWLOntology exOnto = createExAlignOntology(exOntoName, localAxioms, new HashSet());

								//localReasoner.reasoner.loadOntology( exOnto );
								//if there is an extended local onto that is not consistent, we go to pick another "roleConf"
                                                                Connector local2 = new Connector("http://127.0.0.1", 8081);                                                                
                                                                results.add(new Results(local2.isConsistent(uri, localAxioms)));
                                                             }

							}//for "uri"
                                                        int j=0,nbValid=0;
                                                    while(nbValid<localUri.size())
                                                    {
                                                        if(results.get(j).isValid()&&!results.get(j).getResult())
                                                        {
                                                            historiqueIncons.put(localUri.toArray()[j],tmpConf);
                                                            resByUri= false;
                                                            break;
                                                        }
                                                        else{
                                                            if(results.get(j).isValid()&&results.get(j).getResult()){
                                                                nbValid++;
                                                                j++;
                                                            }
                                                            else{
                                                                if(!results.get(j).isValid()){
                                                                    j++;
                                                                }
                                                            }

                                                        }
                                                    }
                                                    if(j>=localUri.size()){
                                                        j=0;
                                                    }


							if ( resByUri ){							 
							 return true;
							}
						} else {

						    localReasoner.reasoner.dispose();//reasoner.unloadOntology( onto );
						}
				  }//while for "confR"
				}// else

			} //while for "confC"
			size++;
		} //while for size

		if( !someConsistentExAlign )
			explanation.setExplanation("<font color=\"red\">All extended alignment ontologies are inconsistent! </font>");
        return false;
	}

	public Set<OWLAxiom> createGlobalAxiomsFromRoleConfBySize( String nameOnto, Set<String> roleConf ) {
		Set<OWLAxiom> axs = new HashSet();
		

		// \top \sqsubseteq \exists R .\top
		for( String r1 : roleConf) {
			OWLClass th = facto.getOWLThing();
                        File temp = new File(r1); // On doit utiliser File tu creer IRI
			OWLProperty r = facto.getOWLObjectProperty( IRI.create( temp ) );
			OWLObjectSomeValuesFrom cl1 =  facto.getOWLObjectSomeValuesFrom((OWLObjectProperty)r, th );
			OWLSubClassOfAxiom ax = facto.getOWLSubClassOfAxiom(th, cl1 );
			axs.add( ax);

                        OWLClass th1 = facto.getOWLThing();
			OWLClass noth = facto.getOWLNothing();

			OWLProperty r2 = facto.getOWLObjectProperty( IRI.create( temp ) );
			OWLObjectAllValuesFrom cl2 =  facto.getOWLObjectAllValuesFrom((OWLObjectProperty)r, noth );
			OWLSubClassOfAxiom ax1 = facto.getOWLSubClassOfAxiom(th1, cl2 );
			axs.add( ax1);
		}

		// \top \sqsubseteq \forall R .\bot
		return axs;
	}
	

	public Set<OWLAxiom> createGlobalAxiomsFromConceptConfBySize( String ontoName, Set<String> conf) {
		Set<OWLAxiom> axs  = new HashSet();
		
		for(String concept : conf) {
			
			OWLClass cls = facto.getOWLClass( IRI.create( concept ) );
			String indName = Integer.toString( getGlobalEntityId() );
			OWLIndividual ind = facto.getOWLNamedIndividual( IRI.create(  ontoName  + "#" + indName )  );
			OWLClassAssertionAxiom ax = facto.getOWLClassAssertionAxiom( cls, ind );
			axs.add(ax);

                        // Adding C 
            		OWLClass cls1 = facto.getOWLClass( IRI.create( concept ) );
			OWLClass cls2 = facto.getOWLNothing();
			OWLSubClassOfAxiom ax1 = facto.getOWLSubClassOfAxiom(cls1, cls2 );
            		axs.add(ax1);
		}
		return axs;
	}

  	boolean FindSetInSet(Set<String> currentSet,HashMap historique,String uri)
        {
            int flag=1;            
            Set<String> temp = (Set<String>)historique.get(uri);
            for(String ax : temp) {
                 for(String st : currentSet) {
                  if(ax.compareTo(st)==0)
                    {
                        flag++;
                        break;
                    }
                 }
            }
            if(flag==temp.size())
                return true;

            return false;
        }
        
	
	//Restore all concepts that have the same representative
	public void buildLocalConceptProj(Set<String> uris){
		
		   HashMap<String, String> globalCMap = systemData.getGlobalConceptMap( );
		   for(String uri: uris) {
			  
			   Set<String> localC = systemData.getLocalMap().getConceptsByUri( uri );
			   
			   //for( String c : localC ) {
			   //   String gc = globalCMap.get(c);
			   //	   for(String re : representativeConcepts) {
			   //		   if(equivClsOfConcepts.get(re).getConcepts().contains( gc ) )
			   //		      localProjectionC.add( c );
			   //	   }   
			   //}
			   
			   conceptProjections.put(uri, localC);
		   }
	}
	
	public Set<String> buildLocalConceptProj(String uri, Set<String> representatives){
		   Set<String> resSet  = new HashSet();
		   
		   Set<String> expandedC   = new HashSet();
		   for(String re : representatives) {
			 
			   expandedC.addAll( equivClsOfConcepts.get(re).getConcepts() );
		   }
		   
		   HashMap<String, String> globalCMap = systemData.getGlobalConceptMap( ); 
		   Set<String> localC = systemData.getLocalMap().getConceptsByUri( uri );
			   
		   for( String c : localC ) {
				String gc = globalCMap.get(c);
				 
			    if(expandedC.contains( gc ) )
					      resSet.add( c );
		   }
			 
		   
		   return resSet;
	}
	
	public void buildLocalRoleProj(Set<String> uris){
		   HashMap<String, String> globalRMap = systemData.getGlobalRoleMap( );
		   for(String uri: uris) {
			   //Set<String> localProjectionR = new HashSet();
			   Set<String> localR = systemData.getLocalMap().getRolesByUri( uri );
			   //for( String r : localR ) {
			   //	   String gr = globalRMap.get( r );
			   //	   for(String re : representativeRoles) {
			   //		   if(equivClsOfRoles.get(re).getRoles().contains( gr ) )
			   //		      localProjectionR.add( r );
			   //	   } 
			   //}
			   roleProjections.put(uri, localR);
		   }	   
	}
	
	public Set<String> buildLocalRoleProj(String uri, Set<String> representatives ){
		  
		   Set<String> resSet  = new HashSet();
		   
		   Set<String> expandedR   = new HashSet();
		   for(String re : representatives) {
			   expandedR.addAll( equivClsOfRoles.get(re).getRoles() );
		   }
		   
		   HashMap<String, String> globalRMap = systemData.getGlobalRoleMap( ); 
		   Set<String> localR = systemData.getLocalMap().getRolesByUri( uri );
		   
		   for( String r : localR ) {
			        
				String gr = globalRMap.get( r );
			
			    if(expandedR.contains( gr ) ){
			    	 
					      resSet.add( r );
			    }
		   }
			 
		   return resSet;
	}
	
	public OWLOntology createExAlignOntology(String ontoName, Set<OWLAxiom> axsFromConceptConf, Set<OWLAxiom> axsFromRoleConf ) {
	    // JE2010: in spite of its name, the same manager is always returned
	        OWLOntologyManager manager = OWLManager.createOWLOntologyManager( );
		OWLOntology initOnto = systemData.getOWLAlignmentOntology();
		Set<OWLAxiom> axiomSet = initOnto.getAxioms();
		//OWLOntology onto = new OWLOntology( manager, new OWLOntologyID( IRI.create(ontoName) ) );
		OWLOntology onto = null;
		try {
			onto = manager.createOntology ( IRI.create(ontoName) );
		}
		catch (OWLOntologyCreationException ex) { ex.printStackTrace(); }

		for ( OWLAxiom ax : axiomSet )  {  
			AddAxiom addaxiom = new AddAxiom(initOnto, ax);
			//addaxiom.accept( changeVisitor );
			manager.applyChange( addaxiom );
		}
		
		//CLD: I do not know why this line is necessary
		localReasoner.loadOntology( onto );
		//localReasoner.reasoner.unloadOntology( onto );
		
		for(OWLAxiom ax: axsFromConceptConf) {
			AddAxiom addaxiom = new AddAxiom(onto, ax);  
			//addaxiom.accept( changeVisitor );
			manager.applyChange( addaxiom );
		}
		
		for(OWLAxiom ax: axsFromRoleConf) {
			AddAxiom addaxiom = new AddAxiom(onto, ax);  
			//addaxiom.accept( changeVisitor );
			manager.applyChange( addaxiom );
		}
		
		return onto;
	}
	
	// "iter" is the union of "iter1" and "iter2" where 
	// + "iter1" is all subsets of initSet - s0, 
	// + "iter2" is formed from each one "i" of "iter1" by adding "s0" to "i". 
	public Set<Set<String>> subsets( Set<String> initSet ) {
		Set<Set<String>> iter = new HashSet<Set<String>>();
		if ( initSet.size()== 0 ){
			Set<String> empty = new HashSet<String>();
			iter.add(empty);
			 
			return iter;
		}
		else {
			
			Set<String> withoutFirst = new HashSet<String>();
			//clone
			for(String st : initSet) 
				withoutFirst.add(st);
			
			Iterator i = withoutFirst.iterator();
			String obj = (String)i.next();
			withoutFirst.remove( obj );
 		
			Set<Set<String>> iter1 = subsets( withoutFirst );
 
			Set<Set<String>> iter2 = new HashSet<Set<String>>();
			
			for(Set<String> id : iter1) {
				    Set<String> tmp = new HashSet<String>(id);
					iter2.add( tmp );
			}
			
			for(Set<String> id : iter2) 
					id.add( obj );
 
			Set<Set<String>> res = new HashSet<Set<String>>();
			 
			
			for(Set<String> k : iter1) {
			    Set<String> tmp = new HashSet<String>(k);
				res.add( tmp );
			}
					 
			for(Set<String> k : iter2) {  
				Set<String> tmp = new HashSet<String>(k);
				res.add( tmp );
			}
			 
			return res;
		}
	}
	
	//generating all triplets (C1, C2, R)
	public Set<RoleConfTriple> getAllTripletsFromConceptConf( Set<String> conf, Set<String> roles ) {
		   Set<RoleConfTriple> iter = new HashSet();
		   Set<String> rNames = roles;
		   for( String c1 : conf) {
			   for( String c2 : conf) {
				   for( String r : rNames) {
					   iter.add( new RoleConfTriple(c1,c2,r) );
				   }
			   }
		   }
		   return iter;
	}
	
	//Add C(a_C) for each C \in cConf, or C \sqsubseteq \bot for each C \notin cConf
	//Add R(a_1, a_2) for each R\in rConf, or \top \sqsubseteq \forall R.\bot for each R\notin rConf 
	public Set<OWLAxiom> createLocalAxiomsFromConf( String uri, Set<String> cConf, Set<String> rConf ) {
		    Set<OWLAxiom> exAxioms = new HashSet();
		    Set<String> compConcepts =  new HashSet();
		    
		    //System.out.println("uri = "+ uri);
		    //System.out.println("c proj = "+conceptProjections.get(uri).toString());
		    if( conceptProjections.get(uri)!=null )
		    if( !conceptProjections.get(uri).isEmpty() ) {
		    	for(String st :  conceptProjections.get(uri)) compConcepts.add(st);
			
			//Set<String> compConcepts =  conceptProjections.get(uri);
			
		    	for( String c1 : cConf) {
		    		 
		    		compConcepts.remove( c1 );
		    		OWLIndividual ind = facto.getOWLNamedIndividual( IRI.create( uri + "#" + getLocalEntityId() ) );
		    		OWLClass cls = facto.getOWLClass( IRI.create( c1 ) );
		    		OWLClassAssertionAxiom ax = facto.getOWLClassAssertionAxiom( cls, ind );
		    		exAxioms.add(ax);
		    	}
			
			//creating axioms C \sqsubseteq \forall R . \neg C'
		    	for(String c2 : compConcepts) {
				 
		    		OWLClass noth = facto.getOWLNothing();
		    		OWLClass cls = facto.getOWLClass( IRI.create( c2 ) );
		    		OWLSubClassOfAxiom ax = facto.getOWLSubClassOfAxiom(cls, noth );
		    		exAxioms.add(ax);
		    	}
		    }   
		    
		    if( roleProjections.get(uri)!=null )
		    if( !roleProjections.get(uri).isEmpty() ) {
		    	Set<String> compRoles =  new HashSet();
		    	for(String st :  roleProjections.get(uri) ) compRoles.add(st);
			
			//Set<String> compRoles =  roleProjections.get(uri);
		    	for( String r1 : rConf) {
		    		//String r2 = systemData.getLRsByGR(r1);
		    		compRoles.remove( r1 );
		    		OWLIndividual ind1 = facto.getOWLNamedIndividual( IRI.create( uri + "#" + getLocalEntityId() ) );
		    		OWLIndividual ind2 = facto.getOWLNamedIndividual( IRI.create( uri + "#" + getLocalEntityId() ) );
		    		OWLProperty r = null;
		    		
		    		if( systemData.getLocalMap().isObjectRole(uri,r1) ) {
		    			r = facto.getOWLObjectProperty( IRI.create( r1 ) );
		    			OWLObjectPropertyAssertionAxiom ax = facto.getOWLObjectPropertyAssertionAxiom( (OWLObjectProperty)r, ind1, ind2 );
		    			exAxioms.add( ax);
		    		}
		    		else {
		    			r = facto.getOWLDataProperty( IRI.create( r1 ) );
		    			OWLDataPropertyAssertionAxiom ax = facto.getOWLDataPropertyAssertionAxiom( (OWLDataProperty)r, ind1, getLocalEntityId() );
		    			exAxioms.add( ax);
		    		}
		    	}
			
			//creating axioms C \sqsubseteq \forall R . \neg C'
		    	for(String r2 : compRoles) {
				 
		    		OWLClass th =   facto.getOWLThing();
		    		OWLClass noth = facto.getOWLNothing();
		    		
		    		if( systemData.getLocalMap().isObjectRole(uri, r2) ) {
		    			OWLProperty r = facto.getOWLObjectProperty( IRI.create( r2 ) );
		    			OWLObjectAllValuesFrom cls = facto.getOWLObjectAllValuesFrom((OWLObjectProperty)r, noth );
		    			OWLSubClassOfAxiom ax = facto.getOWLSubClassOfAxiom(th, cls );
		    			exAxioms.add( ax);
		    		} else {
		    			OWLDataProperty r = facto.getOWLDataProperty( IRI.create( r2 ) );
		    			
		    			//That is not correct since we need something like "facto.getBotDataType()" 
		    			OWLDataAllValuesFrom cls = facto.getOWLDataAllValuesFrom((OWLDataProperty)r, facto.getTopDatatype() );
		    			OWLSubClassOfAxiom ax = facto.getOWLSubClassOfAxiom(th, cls );
		    			exAxioms.add( ax);
		    		}
		    	}
		    }
		   return exAxioms;	
	}

	public Set<OWLAxiom> createLocalAxiomsForOntoEx( String uri, Set<String> cConf ) {
		    Set<OWLAxiom> exAxioms = new HashSet();
		    Set<String> compConcepts =  new HashSet();

		    //System.out.println("uri = "+ uri);
		    //System.out.println("c proj = "+conceptProjections.get(uri).toString());
		    if( conceptProjections.get(uri)!=null )
		    if( !conceptProjections.get(uri).isEmpty() ) {
		    	for(String st :  conceptProjections.get(uri)) compConcepts.add(st);

			//Set<String> compConcepts =  conceptProjections.get(uri);

		    	for( String c1 : cConf) {

		    		compConcepts.remove( c1 );
		    		OWLIndividual ind = facto.getOWLNamedIndividual( IRI.create( uri + "#" + getLocalEntityId() ) );
		    		OWLClass cls = facto.getOWLClass( IRI.create( c1 ) );
		    		OWLClassAssertionAxiom ax = facto.getOWLClassAssertionAxiom( cls, ind );
		    		exAxioms.add( ax);
		    	}

                        //creating axioms C \sqsubseteq \forall R . \neg C'
		    	for(String c2 : compConcepts) {

		    		OWLClass noth = facto.getOWLNothing();
		    		OWLClass cls = facto.getOWLClass( IRI.create( c2 ) );
		    		OWLSubClassOfAxiom ax = facto.getOWLSubClassOfAxiom(cls, noth );
		    		exAxioms.add( ax);
		    	}
                    }


                    return exAxioms;
        }

	// For the case with disjointness correspondences
	// C \sqsubseteq \exists R .C'
	// C \sqsubseteq \forall R .\neg C'
	public Set<OWLAxiom> createGlobalAxiomsFromDisRoleConf( Set<RoleConfTriple> roleConf, Set<RoleConfTriple> allTriplets) {
		Set<OWLAxiom> axs = new HashSet();
		
		Set<RoleConfTriple> compTriplets =  new HashSet();
		for(RoleConfTriple st :  allTriplets) compTriplets.add(st);
		
		//Set<RoleConfTriplet> compTriplets =  allTriplets;
		//creating axioms C \sqsubseteq \exists R .C'
		for( RoleConfTriple triplet : roleConf) {
			//creating the complement of "roleConf" in "allTriplets"
			compTriplets.remove( triplet );
			OWLClass cls1 = facto.getOWLClass( IRI.create( triplet.getConcept1() ) );
			OWLClass cls2 = facto.getOWLClass( IRI.create( triplet.getConcept2() ) );
			OWLProperty r = facto.getOWLObjectProperty( IRI.create( triplet.getRole() ) );
			OWLObjectSomeValuesFrom cl =  facto.getOWLObjectSomeValuesFrom((OWLObjectProperty)r, cls2 );
			
			OWLSubClassOfAxiom ax = facto.getOWLSubClassOfAxiom(cls1, cl );
			axs.add( ax);
		}
		
		//creating axioms C \sqsubseteq \forall R . \neg C'
		for(RoleConfTriple triplet : compTriplets) {
			OWLClass cls1 = facto.getOWLClass( IRI.create( triplet.getConcept1() ) );
			OWLClass cls2 = facto.getOWLClass( IRI.create( triplet.getConcept2() ) );
			OWLClass negCls2 = (OWLClass) facto.getOWLObjectComplementOf(cls2);
			
			OWLProperty r = facto.getOWLObjectProperty( IRI.create( triplet.getRole() ) );
			OWLObjectAllValuesFrom cl =  facto.getOWLObjectAllValuesFrom((OWLObjectProperty)r, negCls2 );
			
			OWLSubClassOfAxiom ax = facto.getOWLSubClassOfAxiom(cls1, cl );
			axs.add( ax);
		}
		
		return axs;
	}
	
	// \top \sqsubseteq \exists R .\top
	// \top \sqsubseteq \forall R .\bot
	public Set<OWLAxiom> createGlobalAxiomsFromRoleConf( String nameOnto, Set<String> roleConf, Set<String> allRoles ) {
		Set<OWLAxiom> axs = new HashSet();
		Set<String> compRoles =  new HashSet();
		for(String st :  allRoles) compRoles.add(st);
		
		// \top \sqsubseteq \exists R .\top
		for( String r1 : roleConf) {
			compRoles.remove( r1 );
			OWLClass th = facto.getOWLThing();
			OWLProperty r = facto.getOWLObjectProperty( IRI.create( r1 ) );
			OWLObjectSomeValuesFrom cl1 =  facto.getOWLObjectSomeValuesFrom((OWLObjectProperty)r, th );
			OWLSubClassOfAxiom ax = facto.getOWLSubClassOfAxiom(th, cl1 );
			axs.add( ax);
		}
		
		// \top \sqsubseteq \forall R .\bot
		for(String r1 : compRoles) {
			OWLClass th = facto.getOWLThing();
			OWLClass noth = facto.getOWLNothing();
			OWLProperty r = facto.getOWLObjectProperty( IRI.create( r1 ) );
			OWLObjectAllValuesFrom cl2 =  facto.getOWLObjectAllValuesFrom((OWLObjectProperty)r, noth );
			OWLSubClassOfAxiom ax = facto.getOWLSubClassOfAxiom(th, cl2 );
			axs.add( ax);
		}
		
		return axs;
	}
	
	//for each  "C \in conf", adding C(a) and for each  "C \notin conf", adding C \sqsubseteq \bot
	//
	public Set<OWLAxiom> createGlobalAxiomsFromConceptConf( String ontoName, Set<String> conf, Set<String> allConcepts ) {
		Set<OWLAxiom> axs  = new HashSet();
		Set<String> compConf =  new HashSet();
		for(String st :  allConcepts) compConf.add(st);
		
		for(String concept : conf) {
			compConf.remove(concept);
			OWLClass cls = facto.getOWLClass( IRI.create( concept ) );
			String indName = Integer.toString( getGlobalEntityId() );
			OWLIndividual ind = facto.getOWLNamedIndividual( IRI.create(  ontoName  + "#" + indName )  );
			OWLClassAssertionAxiom ax = facto.getOWLClassAssertionAxiom( cls, ind );
			axs.add( ax);
		}
		 
		for(String concept : compConf) {
			OWLClass cls1 = facto.getOWLClass( IRI.create( concept ) );
			OWLClass cls2 = facto.getOWLNothing();
			OWLSubClassOfAxiom ax = facto.getOWLSubClassOfAxiom(cls1, cls2 );
			axs.add(ax);
		}
		
		return axs;
	}
	
	// This function fills equivalence classes of concepts i.e. 
	// equivalent concepts are grouped together.
	public void buildEquivClsOfConcepts( OWLOntology onto, Set<String> cNames ) {
		
		localReasoner.loadOntology( onto );
		localReasoner.reasoner.getKB().realize();
		
	    for(String str : cNames ) {
	    	//search for equivalent concepts of "str"
	    	boolean found = false;
	    	Set<String> keys = equivClsOfConcepts.keySet();
	        for(String key : keys) {
	        	GlobalEquivalentConcepts concepts = equivClsOfConcepts.get(key);
	        	if( concepts.getConcepts().contains( str ) ) continue;
	        	
	        	//System.out.println("key concept =" + key);
        		//System.out.println("str concept =" + str);
        		
	        	OWLClass cls1 = facto.getOWLClass( IRI.create( key ) );
	        	OWLClass cls2 = facto.getOWLClass( IRI.create( str ) );

			Node<OWLClass> ns = localReasoner.reasoner.getEquivalentClasses( cls1 );

	        	//if( localReasoner.reasoner.isEquivalentClass( cls1, cls2) ) {
			if( ns.contains( cls2 ) ) {
	        		//System.out.println("equiv classes");
	        		
	        		concepts.addEquivConcept( str );
	        		found = true;
	        		break;
	        	} 
	        }
	        
	        //if no concept in "equivClsOfConcepts" is equivalent to "str" 
	        if( !found ) { 
	        	GlobalEquivalentConcepts it = new GlobalEquivalentConcepts( str );
	        	OWLClass cls = facto.getOWLClass( IRI.create( str ));
			Node<OWLClass> ns1 = localReasoner.reasoner.getEquivalentClasses( cls );
 	        	
			//if(localReasoner.reasoner.isEquivalentClass( cls, facto.getOWLThing()) ) {
			if( ns1.contains(facto.getOWLThing()) ) {
	        		it.setEmptiness(0) ;
 	        	} else if( ! localReasoner.reasoner.isSatisfiable( cls ) ) {
	        		    //if unsatisfiable
	        			it.setEmptiness(1) ;
	        	}
	        	else {
				 NodeSet<OWLNamedIndividual> indis = localReasoner.reasoner.getInstances(facto.getOWLThing(), false);
	        		 //Set<OWLIndividual> indis = localReasoner.reasoner.getIndividuals();
	        		 boolean notEmpty = false;
	        		 for( Node<OWLNamedIndividual> ind: indis) {
				     								
				     	 OWLAxiom ax = facto.getOWLClassAssertionAxiom( cls, (OWLIndividual)ind.getRepresentativeElement() );
	        			 if( localReasoner.reasoner.isEntailed( ax ) ) {
	        				 //if non-empty
	        				 
	        				 it.setEmptiness( 0 );
	        				 notEmpty = true;
	        				 break;
	        			 }
	        		 }
	        		 
	        		 //if not known
	        		 if(!notEmpty)  it.setEmptiness(2);
	        	}
	        	
	        	equivClsOfConcepts.put(str, it);
	        }
	    }
	    
	    localReasoner.dispose();//reasoner.unloadOntology( onto );
	}
	
	//classifying roles into equivalence classes 
	public void buildEquivClsOfRoles( OWLOntology onto , Set<String> rNames ) {
		localReasoner.loadOntology( onto );
		localReasoner.reasoner.getKB().realize();
		
	    for(String str : rNames ) {
	    	boolean found = false;
	    	Set<String> keys = equivClsOfRoles.keySet();
	        for(String key : keys) {
	        	GlobalEquivalentRoles roles = equivClsOfRoles.get(key);
	        	if( roles.getRoles().contains( str ) ) continue;
	        	else {
	        		//check if it can be classified in "key"
                                File temp1 = new File(key);
                                File temp2 = new File(str);
	        		OWLProperty r1 = facto.getOWLObjectProperty( IRI.create(temp1));
	        		OWLProperty r2 = facto.getOWLObjectProperty( IRI.create( temp2 ) );
	        		
				Node<OWLObjectProperty> nr = localReasoner.reasoner.getEquivalentObjectProperties( (OWLObjectProperty)r1 );
	        		//if( localReasoner.reasoner.isEquivalentProperty( (OWLObjectProperty)r1, (OWLObjectProperty)r2) ) {
				if ( nr.contains ((OWLObjectProperty)r2) ) {
	        			//System.out.println("equiv roles");
	        			roles.addEquivRole(str);
	        			found = true;
	        			break;
	        		}
	        	}
	        }
	        
	        if( !found ) { 
	        	GlobalEquivalentRoles it = new GlobalEquivalentRoles( str );
	        	equivClsOfRoles.put(str, it);
	        }
	    }
	    
	    localReasoner.dispose();//reasoner.unloadOntology( onto );
	}
	
	void printStringSet(String name, Set<String> s ){
		for(String st : s) System.out.println( name + "=" + st);
	}

	/*
	public class PowerSetIncremental implements Iterator {

	 private boolean[] membership;

	 private Object[] array;

         int size;

	 public PowerSetIncremental(Object[] array, int size) {

	   this.array=array;

	   this.membership=new boolean[this.array.length];
	   for(int i=0;i<this.array.length;i++)
		this.membership[i]=false;

	 }


	 public PowerSetIncremental(Collection c) {

	   this(c.toArray());

	 }


	 public PowerSetIncremental(Vector v) {

	   this(v.toArray());

	 }
	 
	 public PowerSetIncremental(ArrayList a) {

	   this(a.toArray());
	 }

	
	public Object next()
	{
		return null;
	}
 
	 public Object next(int size) {
		HashSet vec = new HashSet();
		int flag=0;		
		int i=0;
		int flag2=0;
		while(i<this.membership.length){
			if(this.membership[i]){
				continue;
			}else{
				
				if(flag==0){
					flag2=i+size;
				}
				if(i<=flag2){									
					this.membership[i]=!this.membership[i];		 
					flag=1;
	        			vec.add(this.array[i]);					
				}						     
		
			}				
			i++;
		}		
		return vec;

	 }
 

	 public void remove() {

	   throw new UnsupportedOperationException("The PowerSet class does not support the remove method.");
	 }

	 public boolean hasNext() {

	   for(int i=0;i<this.membership.length;i++)

	     if(!this.membership[i])

	       return true;

	   return false;
	 } 
	}


        */

        public class PowerSetBySize implements Iterator {

	 private int[] membership;

	 private Object[] array;

         private int size;

	 public PowerSetBySize(Object[] array, int s) {

           if( s<=0||array.length<s){
               this.array = new Object[0];
               this.size = 0;
               this.membership=new int[0];

           } else {
               this.array = array;
               this.size = s;
               this.membership=new int[this.size];
                for(int i=0; i < this.size - 1; i++)
                        this.membership[i] =  i;
           this.membership[ this.size - 1 ] = this.size - 2 ;
          }
	 }


	 public Object next() {

	   boolean ok=false;

	   for(int i= 0 ;i < this.size ; i++)

	     if(! (this.membership[i] == this.array.length - this.size + i) ) {

	       ok=true;

	       break;
	     }

	   if(!ok)

	     throw(new NoSuchElementException("The next method was called when no more objects remained."));

	   else {

	     for(int n=this.size - 1; n >= 0 ; n--) {

               if (this.membership[n] < this.array.length + n - this.size ) {

                   this.membership[n]++;

                   for(int j = n + 1 ; j < this.size; j++)

                       this.membership[j] = this.membership[j-1] + 1;

		   break;
               }

	     }

	     //Vector vec=new Vector();
	     HashSet vec = new HashSet();
	     
	     for(int i=0;i<this.size;i++)

	        vec.add(this.array[this.membership[i]]);

	     return vec;

	   }

	 }
 

	 public void remove() {

	   throw new UnsupportedOperationException("The PowerSet class does not support the remove method.");
	 }

	 public boolean hasNext() {

	   for(int i=0;i<this.size;i++)

	     if( ! (this.membership[i] == this.array.length + i - this.size ) )

	       return true;

	   return false;
	 } 
	}
	
	public class PowerSet implements Iterator {

	 private boolean[] membership;

	 private Object[] array;

	 public PowerSet(Object[] array) {

	   this.array=array;

	   this.membership=new boolean[this.array.length];

	 }


	 public PowerSet(Collection c) {

	   this(c.toArray());

	 }


	 public PowerSet(Vector v) {

	   this(v.toArray());

	 }
	 
	 public PowerSet(ArrayList a) {

	   this(a.toArray());
	 }

 
	 public Object next() {

	   boolean ok=false;

	   for(int i=0;i<this.membership.length;i++)

	     if(!this.membership[i]) {

	       ok=true;

	       break;
	     }

	   if(!ok)

	     throw(new NoSuchElementException("The next method was called when no more objects remained."));

	   else {

	     int n=0;

	     this.membership[0]=!this.membership[0];

	     boolean carry=!this.membership[0];

	     while(n+1<this.membership.length) {

	       n++;

	       if(carry) {

	         this.membership[n]=!this.membership[n];

	         carry=!this.membership[n];
	       }

	       else break;
	     }

	     //Vector vec=new Vector();
	     HashSet vec = new HashSet();
	     
	     for(int i=0;i<this.membership.length;i++)

	       if(this.membership[i])

	         vec.add(this.array[i]);
	     return vec;

	   }

	 }
 

	 public void remove() {

	   throw new UnsupportedOperationException("The PowerSet class does not support the remove method.");
	 }

	 public boolean hasNext() {

	   for(int i=0;i<this.membership.length;i++)

	     if(!this.membership[i])

	       return true;

	   return false;
	 } 
	}
	
	 	
}
